#ifndef _MATRIX4X4_H_
#define _MATRIX4X4_H_

#include "mathbase.h"
#include <memory.h>
#include <algorithm>

namespace visualization
{

class Matrix4x4
{
	friend class Matrix4x4Manipulator;
	friend class Camera;

	static const unsigned int size;
	static const double eye[16];
	static const unsigned char cofactor_id[16][9];

private:
	double element[16];

	inline int Index(int i, int j)
	{
		return (i<<2) + j;
	}

	inline double Cofactor(int i, int j)
	{
		return element[cofactor_id[i][j]];
	}

public:
	Matrix4x4();
	Matrix4x4(const Matrix4x4 &src);
	Matrix4x4& operator=(const Matrix4x4 &src);
	Matrix4x4& operator+=(const Matrix4x4 &src);
	Matrix4x4& operator-=(const Matrix4x4 &src);

	const double * operator[](unsigned int i) const
	{ return element + (i<<2); }

	double * operator[](unsigned int i) 
	{ return const_cast<double *>(
		(*static_cast<const Matrix4x4 *>(this))[i]); }

	double Determinant();

	void LoadIdentity();
	void Transpose();
	void Adjoint();
	bool Invert();
	void Zero();
};

const Matrix4x4 operator+(const Matrix4x4 &lhs, const Matrix4x4 &rhs);
const Matrix4x4 operator-(const Matrix4x4 &lhs, const Matrix4x4 &rhs);

}

#endif
